package com.qf.service.impl;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.qf.aop.annocation.OrderDataSoruce;
import com.qf.aop.impl.OrderDataSoruceAop;
import com.qf.common.ShopConstatns;
import com.qf.entity.*;
import com.qf.feign.api.AddressService;
import com.qf.feign.api.CarService;
import com.qf.feign.api.StockService;
import com.qf.mapper.OrderDetailMapper;
import com.qf.mapper.OrderMapper;
import com.qf.service.IOrderDetailService;
import com.qf.service.IOrderService;
import com.qf.thread.pool.ShopThreadPool;
import com.qf.utils.UserUtils;
import com.qf.vo.GoodsStockInfo;
import com.qf.vo.OrderInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private AddressService addressService;

    @Autowired
    private CarService carService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IOrderDetailService orderDetailService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private StockService stockService;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    //    @OrderDataSoruce
    @Transactional
    @Override
    public Order createOrder(User user, OrderInfo orderInfo) {

        log.debug(Thread.currentThread().getName());

        // 1.异步查询用户地址
        CompletableFuture<Address> addressFuture = CompletableFuture.supplyAsync(() -> {
            // 1、根据收货地址id查询地址信息
            Address address = addressService.getAddressById(orderInfo.getAddId());
            return address;
        }, ShopThreadPool.executors());


        // 2.异步查询用户的购车
        CompletableFuture<List<Car>> carListFuture = CompletableFuture.supplyAsync(() -> {
            List<Car> carList = carService.getCarListByUid(user.getId());
            return carList;
        }, ShopThreadPool.executors());


        CompletableFuture<Order> orderFuture = carListFuture.thenCombineAsync(addressFuture, (carList, address) -> {
            // 3.计算总价
            BigDecimal totalPrice = new BigDecimal(0.0);
            for (Car car : carList) {
                totalPrice = totalPrice.add(car.getSubTotal());
            }

            // 4、自己生成一个oid
            String oid = createOrderId(user.getId()); // 为什么oid需要自己来做？

            // 5、创建一个Order对象
            Order order = new Order();
            order.setAddress(address.getAddress());
            order.setPhone(address.getPhone());
            order.setName(address.getName());
            order.setPayType(orderInfo.getPayType());
            order.setCreateTime(new Date());
            order.setStatus(1); // 1未支付
            order.setUid(user.getId());
            order.setTotalPrice(totalPrice);
            order.setId(oid);

            // 获取的表的索引，从当前线程的thradLocal里面获取
            Integer tableIndex = OrderDataSoruceAop.getTableIndex();

            // 6、插入订单
            baseMapper.addOrder(order, tableIndex); //orderMapper

            // 7、封装订单详情
            List<OrderDetail> orderDetails = new ArrayList<>();
            for (Car car : carList) {
                Goods goods = car.getGoods();
                OrderDetail od = new OrderDetail(null, oid, car.getGid(), car.getSum(),
                        goods.getGprice(), goods.getGname(), goods.getGdesc(),
                        goods.getGpng(), new Date());
                orderDetails.add(od);
            }

            // 8.插入订单详情
            baseMapper.batchInsertOrderDetail(orderDetails, tableIndex);


            List<GoodsStockInfo> list = new ArrayList<>();
            for (Car car : carList) {
                GoodsStockInfo goodsStockInfo = new GoodsStockInfo();
                goodsStockInfo.setGid(car.getGid());
                goodsStockInfo.setSum(car.getSum());
                goodsStockInfo.setWid(1); // 根据收货地址来判断仓库的id
                list.add(goodsStockInfo);
            }
            // 扣减库存
            stockService.lockGoodsStock(list);

            // 清空购物车
//        carService.clearUserCar(user.getId(),gidList); // delete from t_car where uid = 10 and gid in (1,2,3);

            return order;
        }, ShopThreadPool.executors());

        try {
            return orderFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Order getOrderById(String oid) {

        // 1.根据oid获取userId后四位
        Integer userIdSuff = UserUtils.getUserSuffId(oid);

        // 2.确定数据源
        Integer dbIndex = (userIdSuff % ShopConstatns.ORDER_DB_SIZE) + 1;

        // 3.确定表的索引
        Integer tabIndex = ((userIdSuff / ShopConstatns.ORDER_DB_SIZE) % ShopConstatns.ORDER_TABLE_SIZE) + 1;

        // 4.设置数据源
        DynamicDataSourceContextHolder.push(ShopConstatns.ORDER_DB_PRE + dbIndex);

        // 5、查询订单和订单的详情
        Order order = baseMapper.getOrderById(oid, tabIndex);

        return order;
    }

    @Override
    public void updateOrderStatus(String oid, Integer status) {

        // 1.根据oid获取userId后四位
        Integer userIdSuff = UserUtils.getUserSuffId(oid);

        // 2.确定数据源
        Integer dbIndex = (userIdSuff % ShopConstatns.ORDER_DB_SIZE) + 1;

        // 3.确定表的索引
        Integer tabIndex = ((userIdSuff / ShopConstatns.ORDER_DB_SIZE) % ShopConstatns.ORDER_TABLE_SIZE) + 1;

        // 4.设置数据源
        DynamicDataSourceContextHolder.push(ShopConstatns.ORDER_DB_PRE + dbIndex);

        // 5.修改订单的状态
        baseMapper.updateOrderStatus(oid, status, tabIndex);

    }

    @OrderDataSoruce // 设置数据源
    @Override
    public List<Order> getUserOrderList(User user) {

        // 1.计算表的编号
        Integer userIdSuff = Integer.parseInt(UserUtils.getUserIdSuffByUid(user.getId().toString()));
        Integer tabIndex = ((userIdSuff / ShopConstatns.ORDER_DB_SIZE) % ShopConstatns.ORDER_TABLE_SIZE) + 1;

        // 2.查询用户的订单数据
        return baseMapper.getUserOrderList(user.getId(), tabIndex);
    }

    // 订单ID:时间+用户id后四位+四位随机数+流水号(redis自鞥)
    private String createOrderId(Integer uid) {
        StringBuffer buffer = new StringBuffer();

        // 1.获取当前时间
        String data = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        // 2.用户id后四位
        String uidSuff = UserUtils.getUserIdSuffByUid(uid.toString());

        // 3.四位随机数
        String random = RandomStringUtils.random(4, false, true);

        // 4.获取流水号
        Long orderSenquence = stringRedisTemplate.opsForValue().increment("order-sequence");

        buffer.append(data).append(uidSuff).append(random).append(orderSenquence);

        return buffer.toString();
    }

    public static void main(String[] args) {

//        String userIdSuffByUid = UserUtils.getUserIdSuffByUid("12");
//        System.out.println(userIdSuffByUid);

        String oid = "202106091514150045047521";

    }


}
